﻿using System.Linq.Expressions;
using System.Reflection;
using Library.Distributed;

namespace Library.Linq.Expressions
{
    public abstract class DistributedExpression : Expression
    {
        internal static Expression Context_Current = Expression.Property(null, typeof(Context).GetProperty("Current", BindingFlags.Public | BindingFlags.Static));
        internal static MethodInfo Context_Reduce = typeof(Context).GetMethods().Where(n => n.Name == "Reduce").Where(n => n.GetParameters().Length == 2).First();
        internal static Expression Platform_Current = Expression.Property(null, typeof(Platform).GetProperty("Current", BindingFlags.Public | BindingFlags.Static));
        internal static MethodInfo Platform_Invoke = typeof(Platform).GetMethods().Where(n => n.Name == "Invoke").Where(n => n.GetParameters().Length == 2 && n.GetGenericArguments().Length == 1).First();
        internal static MethodInfo Platform_Invoke3 = typeof(Platform).GetMethods().Where(n => n.Name == "Invoke").Where(n => n.GetParameters().Length == 3 && n.GetGenericArguments().Length == 3).First();

        public static Expression NodeIndex()
        {
            return new NodeIndexExpression();
        }
        public static Expression NodeCount()
        {
            return new NodeCountExpression();
        }
        public static Expression NodeExtent()
        {
            return new NodeExtentExpression();
        }

        public static Expression AllGather(Expression operand)
        {
            return new AllGatherExpression(operand);
        }
        public static Expression AllToAll(Expression operand)
        {
            return new AllToAllExpression(operand);
        }

        public static Expression Barrier()
        {
            return new BarrierExpression();
        }
        public static Expression Barrier(Expression timeout)
        {
            return new BarrierExpression(timeout);
        }
        public static Expression MemoryBarrier()
        {
            return new MemoryBarrierExpression();
        }

        public static Expression Reduce(Expression operand, LambdaExpression reduction)
        {
            return new ReductionExpression(operand, reduction);
        }
        public static Expression ReduceAdd(Expression operand)
        {
            return new ReductionAdditionExpression(operand);
        }
        public static Expression ReduceAnd(Expression operand)
        {
            return new ReductionAndExpression(operand);
        }
        public static Expression ReduceExclusiveOr(Expression operand)
        {
            return new ReductionExclusiveOrExpression(operand);
        }
        public static Expression ReduceMaximum(Expression operand)
        {
            return new ReductionMaximumExpression(operand);
        }
        public static Expression ReduceMinimum(Expression operand)
        {
            return new ReductionMinimumExpression(operand);
        }
        public static Expression ReduceOr(Expression operand)
        {
            return new ReductionOrExpression(operand);
        }

        // ...

        

        internal DistributedExpression() { }

        public sealed override bool CanReduce
        {
            get
            {
                return true;
            }
        }

        public sealed override ExpressionType NodeType
        {
            get
            {
                return ExpressionType.Extension;
            }
        }
    }
}
